package shop.bestellverwaltung.service; import static shop.util.Constants.KEINE_ID; import static shop.util.Constants.LOADGRAPH; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.enterprise.context.Dependent; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.persistence.EntityGraph; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import com.google.common.collect.ImmutableMap; import shop.bestellverwaltung.domain.Bestellposition; import shop.bestellverwaltung.domain.Bestellung; import shop.bestellverwaltung.domain.Lieferung; import shop.kundenverwaltung.domain.AbstractKunde; import shop.kundenverwaltung.service.KundenService; import shop.util.interceptor.Log; @Dependent @Log public class BestellungServiceImpl implements Serializable, BestellungService { private static final long serialVersionUID = 7768151241843171545L; @Inject private transient EntityManager em; @Inject private KundenService ks; @Inject @NeueBestellung private transient Event<Bestellung> event; @Override @NotNull(message = "{bestellung.notFound.id}") public Bestellung findBestellungById(Long id, FetchType fetch) { if (id == null) { return null; } Bestellung bestellung; EntityGraph<?> entityGraph; Map<String, Object> props; switch (fetch) { case NUR_BESTELLUNG: bestellung = em.find(Bestellung.class, id); break; case MIT_LIEFERUNGEN: entityGraph = em.getEntityGraph(Bestellung.GRAPH_LIEFERUNGEN); props = ImmutableMap.of(LOADGRAPH, (Object) entityGraph); bestellung = em.find(Bestellung.class, id, props); break; default: bestellung = em.find(Bestellung.class, id); break; } return bestellung; } @Override @NotNull(message = "{bestellung.kunde.notFound.id}") public AbstractKunde findKundeById(Long id) { try { return em.createNamedQuery(Bestellung.FIND_KUNDE_BY_ID, AbstractKunde.class) .setParameter(Bestellung.PARAM_ID, id) .getSingleResult(); } catch (NoResultException e) { return null; } } @Override @Size(min = 1, message = "{bestellung.notFound.kunde}") public List<Bestellung> findBestellungenByKunde(AbstractKunde kunde) { if (kunde == null) { return Collections.emptyList(); } return em.createNamedQuery(Bestellung.FIND_BESTELLUNGEN_BY_KUNDE, Bestellung.class) .setParameter(Bestellung.PARAM_KUNDE, kunde) .getResultList(); } @Override @Size(min = 1, message = "{bestellung.notFound.ids}") public List<Bestellung> findBestellungenByIds(List<Long> ids, FetchType fetch) { if (ids == null || ids.isEmpty()) { return Collections.emptyList(); } final CriteriaBuilder builder = em.getCriteriaBuilder(); final CriteriaQuery<Bestellung> criteriaQuery = builder.createQuery(Bestellung.class); final Root<Bestellung> b = criteriaQuery.from(Bestellung.class); final Path<Long> idPath = b.get("id"); final List<Predicate> predList = new ArrayList<>(); for (Long id : ids) { final Predicate equal = builder.equal(idPath, id); predList.add(equal); } final Predicate[] predArray = new Predicate[predList.size()]; final Predicate pred = builder.or(predList.toArray(predArray)); criteriaQuery.where(pred).distinct(true); final TypedQuery<Bestellung> query = em.createQuery(criteriaQuery); if (FetchType.MIT_LIEFERUNGEN.equals(fetch)) { final EntityGraph<?> entityGraph = em.getEntityGraph(Bestellung.GRAPH_LIEFERUNGEN); query.setHint(LOADGRAPH, entityGraph); } return query.getResultList(); } @Override public Bestellung createBestellung(Bestellung bestellung, Long kundeId) { if (bestellung == null) { return null; } final AbstractKunde kunde = ks.findKundeById(kundeId, KundenService.FetchType.MIT_BESTELLUNGEN); return createBestellung(bestellung, kunde); } @Override public Bestellung createBestellung(Bestellung bestellung, AbstractKunde kunde) { if (bestellung == null) { return null; } if (!em.contains(kunde)) { kunde = ks.findKundeById(kunde.getId(), KundenService.FetchType.MIT_BESTELLUNGEN); } kunde.addBestellung(bestellung); bestellung.setKunde(kunde); bestellung.setId(KEINE_ID); for (Bestellposition bp : bestellung.getBestellpositionen()) { bp.setId(KEINE_ID); } em.persist(bestellung); event.fire(bestellung); return bestellung; } @Override @Size(min = 1, message = "{lieferung.notFound.nr}") public List<Lieferung> findLieferungen(String nr) { final EntityGraph<?> entityGraph = em.getEntityGraph(Lieferung.GRAPH_BESTELLUNGEN); return em.createNamedQuery(Lieferung.FIND_LIEFERUNGEN_BY_LIEFERNR, Lieferung.class) .setParameter(Lieferung.PARAM_LIEFERNR, nr) .setHint(LOADGRAPH, entityGraph) .getResultList(); } @Override public Lieferung createLieferung(Lieferung lieferung, List<Bestellung> bestellungen) { if (lieferung == null || bestellungen == null || bestellungen.isEmpty()) { return null; } final List<Long> ids = new ArrayList<>(); for (Bestellung b : bestellungen) { ids.add(b.getId()); } bestellungen = findBestellungenByIds(ids, FetchType.MIT_LIEFERUNGEN); lieferung.setBestellungenAsList(bestellungen); for (Bestellung bestellung : bestellungen) { bestellung.addLieferung(lieferung); } lieferung.setId(KEINE_ID); em.persist(lieferung); return lieferung; } }